defmodule Neo4jRepo do
	@moduledoc """
	    增删改查, 只用于最简单的设置属性,关系等,
	        有返回数据的时候不用, 或者是复杂操作的时候不用(判断参数的正确性等)
	"""


	defmacro __using__(_env) do
		quote location: :keep do

			import UserLib

			@doc """
			    struct: 模块结构体,可以包含关系,字段等
			"""
			def insert(uid_or_user, struct) when is_map(struct)  do
				uid_or_user =
					if Kernel.is_map(uid_or_user) do
						get_project_id(uid_or_user)
					else
						uid_or_user
					end
				Neo4jLib.insert(uid_or_user, __MODULE__.new(struct))
				|> Neo4jDb.insert()
			end
			@doc """
			    unique_key: 唯一uid
			    struct: 模块结构体, 可以包含关系,字段等
			"""
			def update(uid_or_user, unique_key, struct) do
				uid_or_user = if Kernel.is_map(uid_or_user) do
					get_project_id(uid_or_user)
				else
					uid_or_user
				end
				struct = MapLib.set_struct(struct, __MODULE__)
				Neo4jLib.update(uid_or_user, unique_key, struct)
				|> Neo4jDb.update()
			end
			@doc """
			    unique_keys: [唯一uid]
			"""
			def delete(uid_or_user, unique_keys) when is_list(unique_keys) do
				args = %{:unique_keys => unique_keys}
				delete(uid_or_user, args)
			end

			@doc """
			    map: %{
			    }
			"""
			def delete(uid_or_user, map) do
				uid_or_user = if Kernel.is_map(uid_or_user) do
					get_project_id(uid_or_user)
				else
					uid_or_user
				end
				Neo4jLib.delete(uid_or_user, __MODULE__, map)
				|> Neo4jDb.write()
			end

			# args: %{"关系对象" => [对象主键]|对象主键}
			def create_relation(uid_or_user, unique_key, args) do
				uid_or_user = if Kernel.is_map(uid_or_user) do
					get_project_id(uid_or_user)
				else
					uid_or_user
				end
				Neo4jLib.create_rel(uid_or_user, unique_key, MapLib.set_struct(args, __MODULE__))
				|> Neo4jDb.create_rel()
			end

			def delete_relation(uid_or_user, unique_key, args) do
				uid_or_user = if Kernel.is_map(uid_or_user) do
					get_project_id(uid_or_user)
				else
					uid_or_user
				end
				Neo4jLib.delete_rel(uid_or_user, unique_key, MapLib.set_struct(args, __MODULE__))
				|> Neo4jDb.delete_rel()
			end

			@doc """
			    match:[]
			    optional: []
			    select: %{"obj1" => ["字段1"...], "obj2" => ["字段2"]}
			    where: ["字段1", "字段2"]
			        字段1: 对象 + 字段 = 值; ex: "technique.name = 'test'", "technique.name contains('test')"
			    where: %{"字段1" => "值", "OR" => %{}, "IS" => %{}, "like" => %{}, ">" => %{}}
			      字段1: 对象+字段; ex: technique.name => 'test', contains.step => 2, contains.step => [1, 2]
			      值: list, string, integer, float...
			"""
			def get(uid_or_user, select, where, match \\ [], optional \\ []) do
				{str, params} = Neo4jLib.get(uid_or_user, __MODULE__, match, optional, select, where)
				Neo4jDb.get_one(str, params)
				|> Map.get("entries")
			end

			def get!(uid_or_user, select, where, match \\ [], optional \\ []) do
				v = get(uid_or_user, match, optional, select, where)
				v == [] && raise TipError, "不存在"
				v
			end

			def one(uid_or_user, select, where, default \\ nil, match \\ [], optional \\ []) do
				case get(uid_or_user, match, optional, select, where) do
					[] ->
						default
					v ->
						hd(v)
				end
			end

			def one!(uid_or_user, select, where, default \\ nil, match \\ [], optional \\ []) do
				v = one(uid_or_user, match, optional, select, where)
				v == nil && throw({:error, "不存在"})
				v
			end
			defoverridable insert: 2,
			               update: 3,
			               delete: 2,
			               create_relation: 3,
			               delete_relation: 3,
			               get: 5,
			               get!: 5,
			               one: 6,
			               one!: 6

		end
	end

end
